<?php

namespace controller\admin;

defined('IA_ROOT') || exit();

use facade\Model;
use facade\View;
use facade\Util;

// 用户管理
class User extends Base
{
    // 列表
    public function index()
    {
        if (Util::isAjax()) {
            $param = Util::param();
            $start = ($param['page'] - 1) * $param['limit'];
            $limit = $param['limit'];
            // $where = "`id` <= (SELECT `id` FROM `user` ORDER BY `id` DESC LIMIT $start, 1)";
            $where = "1 = 1";
            // 搜索
            if (!empty($param['search'])) {
                foreach ((array)$param['search'] as $k => $v) {
                    if (strlen($v)) {
                        if (in_array($k, ['status', 'role_id'])) {
                            $where .= " AND `$k` = '$v'";
                        } else {
                            $where .= " AND `$k` like '%{$v}%'";
                        }
                    }
                }
            }
            $count = Model::fetchColumn("SELECT COUNT(*) FROM `user` WHERE $where ORDER BY `id` DESC");
            $data = Model::fetchAll("SELECT * FROM `user` WHERE $where ORDER BY `id` DESC LIMIT $start, $limit");
            $role = Util::formatKey($this->role);
            if ($count) {
                $res['code'] = 0;
            } else {
                $res['code'] = 1;
                $res['msg'] = '暂无记录';
            }
            $res['count'] = $count;
            $res['data'] = array_map(function ($item) use ($role) {
                $item['role_name'] = isset($role[$item['role_id']]) ? $role[$item['role_id']]['name'] : '';
                if (preg_match('#(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)#i', $item['avatar'], $match)) {
                    $item['avatar'] = $this->site_url . $match[1];
                }
                $item['reg_time'] = date('Y-m-d H:i', $item['reg_time']);
                $item['first_login'] = date('Y-m-d H:i', $item['first_login']);
                $item['last_login'] = date('Y-m-d H:i', $item['last_login']);
                return $item;
            }, $data);
            exit(json_encode($res));
        }
        View::assign('role', $this->role);
        View::display('admin/user/index.html');
    }

    // 创建
    public function create()
    {
        View::assign('role', $this->role);
        View::display('admin/user/create.html');
    }

    // 保存
    public function save()
    {
        $param = Util::param(['username', 'password', 'email', 'nickname', 'phone', 'avatar', 'role_id', 'status']);
        if (empty($param['username']) || !preg_match('#^[a-z0-9_-]{3,12}$#', $param['username']))
            Util::errMsg('用户名3~12位只能字母数字下划线或中划线');
        $check = Model::fetchColumn("SELECT `username` FROM `user` WHERE `username`=:username ORDER BY `id`", [':username' => $param['username']]);
        $check && Util::errMsg('用户名已存在');
        if (empty($param['password']) || strlen($param['password']) < 5) {
            Util::errMsg('密码至少5位');
        } else {
            $param['password'] = md5(base64_encode($param['password']));
        }
        if (!isset($param['email']) || (!empty($param['email']) && !filter_var($param['email'], FILTER_VALIDATE_EMAIL)))
            Util::errMsg('邮箱格式错误');
        if (!empty($param['nickname']) && !preg_match('#^[\x{4e00}-\x{9fa5}A-Za-z0-9_-]{2,12}$#u', $param['nickname']))
            Util::errMsg('昵称2~12位只能中英文字母数字下划线中划线');
        if (!empty($param['nickname'])) {
            $check = Model::fetchColumn("SELECT `nickname` FROM `user` WHERE `nickname`=:nickname ORDER BY `id`", [':nickname' => $param['nickname']]);
            $check && Util::errMsg('昵称已存在');
        }
        if (!empty($param['phone']) && !preg_match('#^1((34[0-8]\d{7})|((3[0-3|5-9])|(4[5-7|9])|(5[0-3|5-9])|(66)|(7[2-3|5-8])|(8[0-9])|(9[1|8|9]))\d{8})$#', $param['phone']))
            Util::errMsg('手机号码不正确');
        if (!empty($param['phone'])) {
            $check = Model::fetchColumn("SELECT `phone` FROM `user` WHERE `phone`=:phone ORDER BY `id`", [':phone' => $param['phone']]);
            $check && Util::errMsg('手机号码已存在');
        }
        if (!empty($param['avatar'])) {
            !preg_match('/\.(gif|jpe?g|png|webp|svg)$/i', $param['avatar']) && Util::errMsg('图片格式错误');
            if (preg_match('#(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)#i', $param['avatar'], $match)) {
                $param['avatar'] = $match[1];
            }
        }
        $role_ids = array_map(function ($item) {
            return $item['id'];
        }, $this->role);
        $param['role_id'] = intval($param['role_id']);
        if (!empty($param['role_id']) && !in_array($param['role_id'], $role_ids))
            Util::errMsg('角色数据错误');
        if (!isset($param['status']) || !in_array($param['status'], [0, 1]))
            Util::errMsg('状态数据错误');

        // 写入数据库记录日志
        $param['reg_time'] = time();
        $lastInsertId = Model::insert('user', $param);
        if ($lastInsertId) {
            // 修改媒体状态
            if (preg_match('#(/static/upload/[^\.]+\.(gif|jpe?g|png|webp|svg))#i', $param['avatar'], $match)) {
                if (is_file(IA_ROOT . $match[1])) {
                    Model::update('media', ['status' => 0], ['path' => $match[1]]);
                } else {
                    Model::update('media', ['status' => 2], ['path' => $match[1]]);
                }
            }
            $this->log('创建用户', "创建用户 {$param['username']} 成功", 0);
            Util::errMsg(['code' => 0, 'msg' => '创建用户成功']);
        } else {
            $this->log('创建用户', "创建用户 {$param['username']} 失败", 1);
            Util::errMsg(['code' => 1, 'msg' => '创建用户失败']);
        }
    }

    // 编辑
    public function edit($id = 0)
    {
        $user = Model::fetch("SELECT * FROM `user` WHERE `id`=:id", [':id' => $id]);
        !$user && Util::errMsg('ID错误');
        // 获取验证码
        if (Util::isAjax()) {
            $email = Util::param('email');
            if (empty($email) || $email == $user['email']) {
                Util::errMsg('仅在邮箱发生改变时需要验证码');
            }
            // 随机验证码
            if (!session_id()) session_start();
            $verycode = mt_rand(100000, 999999);
            $_SESSION['email_verycode'] = [
                'code' => $verycode,
                'email' => $email,
                'expire' => time() + 600 // 10分钟有效期
            ];
            $smtp = ['email' => '', 'code' => '', 'service' => ''];
            $setting = Model::fetch('SELECT * FROM `setting` WHERE id=:id ORDER BY `id` ASC LIMIT 1', [':id' => 1]);
            if ($setting && ($check = json_decode($setting['value'], true)) && !empty($check['email']) && !empty($check['code']) && !empty($check['service'])) {
                $smtp = ['email' => $check['email'], 'code' => $check['code'], 'service' => $check['service']];
            }
            (empty($smtp['email']) || empty($smtp['code']) || empty($smtp['service'])) && Util::errMsg('SMTP 配置错误');
            $sendmail = Util::sendMail($email, '您的验证码', '您的验证码: ' . $verycode . ' ' . '验证码 10 分钟内有效', $smtp['email'], $smtp['code'], $smtp['service']);
            if ($sendmail === true) return Util::errMsg(['code' => 0, 'msg' => '验证邮件已发送至 ' . $email]);
            Util::errMsg(['code' => 1, 'msg' => $sendmail]);
            return;
        }
        $role = $this->role;
        View::assign(compact('user', 'role'));
        View::display('admin/user/edit.html');
    }

    // 更新
    public function update()
    {
        $param = Util::param(['id', 'password', 'email', 'nickname', 'phone', 'avatar', 'role_id', 'status']);
        $user = Model::fetch("SELECT * FROM `user` WHERE `id`=:id", [':id' => $param['id']]);
        !$user && Util::errMsg('ID错误');
        if (!empty($param['password'])) {
            strlen($param['password']) < 5 && Util::errMsg('密码至少5位');
            $param['password'] = md5(base64_encode($param['password']));
        } else {
            unset($param['password']);
        }
        if (!isset($param['email']) || (!empty($param['email']) && !filter_var($param['email'], FILTER_VALIDATE_EMAIL))) {
            Util::errMsg('邮箱格式错误');
        }
        if (!session_id()) session_start();
        if (!empty($param['email']) && $param['email'] !== $user['email']) {
            // 修改邮箱确认验证码
            $check = Model::fetchColumn("SELECT `email` FROM `user` WHERE `email`=:email ORDER BY `id`", [':email' => $param['email']]);
            $check && $check !== $user['email'] && Util::errMsg('邮箱已存在');
            $captcha = Util::param('captcha');
            empty($captcha) && Util::errMsg('修改邮箱请填写验证码');
            if (!isset($_SESSION['email_verycode']) || !isset($_SESSION['email_verycode']['code']) || !isset($_SESSION['email_verycode']['email']) || $_SESSION['email_verycode']['code'] != $captcha || empty($_SESSION['email_verycode']['expire']) || $_SESSION['email_verycode']['expire'] < time())
                Util::errMsg('验证码错误或已过期');
        }
        if (!empty($param['nickname']) && !preg_match('#^[\x{4e00}-\x{9fa5}A-Za-z0-9_-]{2,12}$#u', $param['nickname']))
            Util::errMsg('昵称2~12位只能中英文字母数字下划线中划线');
        if (!empty($param['nickname'])) {
            $check = Model::fetchColumn("SELECT `nickname` FROM `user` WHERE `nickname`=:nickname ORDER BY `id`", [':nickname' => $param['nickname']]);
            $check && $check !== $user['nickname'] && Util::errMsg('昵称已存在');
        }
        if (!empty($param['phone']) && !preg_match('#^1((34[0-8]\d{7})|((3[0-3|5-9])|(4[5-7|9])|(5[0-3|5-9])|(66)|(7[2-3|5-8])|(8[0-9])|(9[1|8|9]))\d{8})$#', $param['phone']))
            Util::errMsg('手机号码不正确');
        if (!empty($param['phone'])) {
            $check = Model::fetchColumn("SELECT `phone` FROM `user` WHERE `phone`=:phone ORDER BY `id`", [':phone' => $param['phone']]);
            $check && $check !== $user['phone'] && Util::errMsg('手机号码已存在');
        }
        if (!empty($param['avatar'])) {
            !preg_match('#/static/upload/.+?\.[png|jpg|jpeg|gif]#', $param['avatar']) && Util::errMsg('图片格式错误');
            $param['avatar'] = str_replace($this->site_url, '', $param['avatar']);
        }
        $role_ids = array_map(function ($item) {
            return $item['id'];
        }, $this->role);
        $param['role_id'] = intval($param['role_id']);
        if (!empty($param['role_id']) && !in_array($param['role_id'], $role_ids))
            Util::errMsg('角色数据错误');
        if (!isset($param['status']) || !in_array($param['status'], [0, 1]))
            Util::errMsg('状态数据错误');
        $param['id'] == 1 && $param['status'] == 1 && Util::errMsg('管理员不可禁用');

        // 清除需要修改邮箱的验证码
        if (!empty($param['email']) && $param['email'] !== $user['email'] && isset($_SESSION['email_verycode'])) {
            unset($_SESSION['email_verycode']);
        }

        // 更新数据库记录日志
        $rowCount = Model::update('user', $param, ['id' => $param['id']]);
        // 修改媒体状态
        $paths = [0 => [], 1 => [], 2 => []];
        if (preg_match('#(/static/upload/[^\.]+\.(gif|jpe?g|png|webp|svg))#i', $user['avatar'], $match)) {
            if (is_file(IA_ROOT . $match[1])) {
                $paths[1][] = $match[1];
            } else {
                $paths[2][] = $match[1];
            }
        }
        if (preg_match('#(/static/upload/[^\.]+\.(gif|jpe?g|png|webp|svg))#i', $param['avatar'], $match)) {
            if (is_file(IA_ROOT . $match[1])) {
                $paths[0][] = $match[1];
            } else {
                $paths[2][] = $match[1];
            }
        }
        $paths[1] = array_filter($paths[1], function ($item) use ($paths) {
            return !in_array($item, $paths[0]);
        });
        $paths[1] && Model::update('media', ['status' => 1], ['path' => array_unique($paths[1])]);
        $paths[0] && Model::update('media', ['status' => 0], ['path' => array_unique($paths[0])]);
        $paths[2] && Model::update('media', ['status' => 2], ['path' => array_unique($paths[2])]);
        if ($rowCount) {
            $this->log('编辑用户', "编辑用户 {$user['username']} 成功", 0);
            Util::errMsg(['code' => 0, 'msg' => '编辑用户成功']);
        } else {
            $this->log('编辑用户', "没有改变 {$user['username']} 信息", 0);
            Util::errMsg(['code' => 1, 'msg' => '没有改变信息']);
        }
    }

    // 修改属性
    public function modify()
    {
        $param = Util::param(['id', 'field', 'value']);
        empty($param['id']) && Util::errMsg('ID错误');
        $user = Model::fetch("SELECT * FROM `user` WHERE `id`=:id", [':id' => $param['id']]);
        !$user && Util::errMsg('ID非法');
        (empty($param['field']) || !in_array($param['field'], ['nickname', 'phone', 'status'])) && Util::errMsg('非法字段');

        if ($param['field'] == 'nickname' && !empty($param['value']) && !preg_match('#^[\x{4e00}-\x{9fa5}A-Za-z0-9_-]{2,12}$#u', $param['value']))
            Util::errMsg('昵称2~12位只能中英文字母数字下划线中划线');
        if ($param['field'] == 'nickname' && !empty($param['value'])) {
            $check = Model::fetchColumn("SELECT `nickname` FROM `user` WHERE `nickname`=:nickname ORDER BY `id`", [':nickname' => $param['value']]);
            $check && $check !== $user['nickname'] && Util::errMsg('昵称已存在');
        }
        if ($param['field'] == 'phone' && !preg_match('#^1((34[0-8]\d{7})|((3[0-3|5-9])|(4[5-7|9])|(5[0-3|5-9])|(66)|(7[2-3|5-8])|(8[0-9])|(9[1|8|9]))\d{8})$#', $param['value']))
            Util::errMsg('手机号码不正确');
        if ($param['field'] == 'phone' && !empty($param['value'])) {
            $check = Model::fetchColumn("SELECT `phone` FROM `user` WHERE `phone`=:phone ORDER BY `id`", [':phone' => $param['value']]);
            $check && $check !== $user['phone'] && Util::errMsg('手机号码已存在');
        }
        $param['id'] == 1 && $param['field'] == 'status' && $param['value'] == 1 && Util::errMsg('管理员不可禁用');

        // 更新数据库记录日志
        $rowCount = Model::update('user', [$param['field'] => $param['value']], ['id' => $param['id']]);
        if ($rowCount) {
            $this->log('修改属性', "修改属性 {$param['field']}: {$user[$param['field']]} -> {$param['value']} 成功", 0);
            Util::errMsg(['code' => 0, 'msg' => '修改成功']);
        } else {
            $this->log('修改属性', "修改属性 {$param['field']}: {$user[$param['field']]} -> {$param['value']} 失败", 1);
            Util::errMsg(['code' => 1, 'msg' => '修改失败']);
        }
    }

    // 删除
    public function delete()
    {
        $param = Util::param(['id']);
        (empty($param) || !isset($param['id'])) && Util::errMsg('请选择数据');
        in_array('1', (array)$param['id']) && Util::errMsg('管理员不可删除');
        in_array('2', (array)$param['id']) && Util::errMsg('游客不可删除');
        $idStr = implode(',', (array)$param['id']);
        $users = Model::fetchAll("SELECT `username`, `avatar` FROM `user` WHERE `id` IN ($idStr)");
        $paths = [0 => [], 1 => [], 2 => []];
        $userNames = [];
        foreach ($users as $user) {
            $userNames[] = $user['username'];
            if (preg_match('#(/static/upload/[^\.]+\.(gif|jpe?g|png|webp|svg))#i', $user['avatar'], $match)) {
                if (is_file(IA_ROOT . $match[1])) {
                    $paths[1][] = $match[1];
                } else {
                    $paths[2][] = $match[1];
                }
            }
        }
        // 删除数据记录日志
        $rowCount = Model::delete('user', ['id' => $param['id']]);
        if ($rowCount) {
            // 修改媒体状态
            $paths[1] && Model::update('media', ['status' => 1], ['path' => array_unique($paths[1])]);
            $paths[2] && Model::update('media', ['status' => 2], ['path' => array_unique($paths[2])]);
            $this->log('删除用户', "删除用户 " . implode(' ', $userNames) . " 成功", 0);
            Util::errMsg(['code' => 0, 'msg' => '删除成功']);
        } else {
            $this->log('删除用户', "删除用户 " . implode(' ', $userNames) . " 失败", 1);
            Util::errMsg(['code' => 1, 'msg' => '删除失败']);
        }
    }
}
